package com.topscomm.mis.cbb.file.compare.word.handler.impl;

import com.topscomm.basic.exception.ServiceException;
import com.topscomm.mis.cbb.file.compare.cj.CjSystemConst;
import com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity;
import com.topscomm.mis.cbb.file.compare.cj.pojo.dto.CompareItemsDto;
import com.topscomm.mis.cbb.file.compare.word.handler.BasicCompareHandler;
import com.topscomm.mis.cbb.file.compare.word.handler.IDocumentCompareHandler;
import com.topscomm.mis.cbb.file.compare.word.handler.IParagraphCompareHandler;
import com.topscomm.mis.cbb.file.compare.word.handler.ITableCompareHandler;
import com.topscomm.mis.cbb.file.compare.word.service.PoiCommentService;
import com.topscomm.mis.cbb.file.compare.word.util.PoiWordUtil;
import com.topscomm.pub.util.ConvertUtil;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.awt.geom.QuadCurve2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import static com.topscomm.mis.cbb.file.compare.cj.CjSystemConst.SectionFlag;

/**
 * @description:
 * @author: zhanglongfei
 * @date: 2023/2/21 9:18
 */
@Component
public class DefaultDocumentCompareHandler extends BasicCompareHandler implements
    IDocumentCompareHandler {

    @Autowired(required = false)
    private List<IParagraphCompareHandler> paragraphCompareHandlers;
    @Autowired(required = false)
    private List<ITableCompareHandler> tableCompareHandlers;

    /**
     * @param document1        :
     * @param document2        :
     * @param compareItemsDto: 2023-06-14 wxm添加参数：支持对比项自定义
     * @description: 比对两个文档差异，返回差异明细 文档级别的比对，主要查看页面的表格、段落的数量、顺序是否匹配，不匹配的需要追加匹配
     * @return: java.util.List<com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity>
     * @author: zhanglongfei
     * @date: 2023/2/21 13:46
     * @modify:
     */
    @Override
    public List<CjCompareJobResultEntity> doCompare(XWPFDocument document1, XWPFDocument document2,
        CompareItemsDto compareItemsDto) {
        List<CjCompareJobResultEntity> resultList = new ArrayList<>();

        int i = 0,j=0;
        int page = 1;
        while (i < Math.max(document1.getBodyElements().size(), document2.getBodyElements().size())) {
            IBodyElement currentElement1 =
                document1.getBodyElements().size() > i ? document1.getBodyElements().get(i) : null;
            IBodyElement currentElement2 =
                document2.getBodyElements().size() > j ? document2.getBodyElements().get(j) : null;
            String elementName1 =
                currentElement1 != null ? currentElement1.getElementType().name() : "";
            String elementName2 =
                currentElement2 != null ? currentElement2.getElementType().name() : "";
            // 同为段落或同为表格才进行对比，否则需要先补充一致再进行对比
            int tempPage = page;
            if(currentElement1 != null){
                tempPage = getSectionIndex(document1, currentElement1);
            }
            if (page!=tempPage) {
                page = tempPage;
                i++;
                continue;
            }
            boolean iscontinue = false;
            if("PARAGRAPH".equals(elementName1)){
                XWPFParagraph convertedParagraph1 = (XWPFParagraph) currentElement1;
                // 对转换后的 XWPFParagraph 对象进行操作
                String temp = convertedParagraph1.getText().replaceAll("\n","");
                if("".equals(temp)){
                    iscontinue = true;
                    i++;
                } else if(convertedParagraph1.getRuns().size()==0){
                    iscontinue = true;
                    i++;
                } else if(convertedParagraph1.getRuns().size()==1){
                    XWPFRun run = convertedParagraph1.getRuns().get(0);
                    if("\n".equals(ConvertUtil.convertToString(run)) || ConvertUtil.convertToString(run).trim().isEmpty()) {
                        iscontinue = true;
                        i++;
                    }
                } else {
                    String tempText = convertedParagraph1.getText();
                    System.out.println(tempText.replaceAll(" ",""));
                    if("".equals(tempText.replaceAll(" ",""))){
                        iscontinue = true;
                        i++;
                    }
                }
            }
            if("PARAGRAPH".equals(elementName2)){
                XWPFParagraph convertedParagraph2 = (XWPFParagraph) currentElement2;
                // 对转换后的 XWPFParagraph 对象进行操作
                String temp = convertedParagraph2.getText().replaceAll("\n","");
                if("".equals(temp)){
                    iscontinue = true;
                    j++;
                } else if(convertedParagraph2.getRuns().size()==0){
                    iscontinue = true;
                    j++;
                } else if (convertedParagraph2.getRuns().size()==1) {
                    XWPFRun run = convertedParagraph2.getRuns().get(0);
                    if("\n".equals(ConvertUtil.convertToString(run)) || ConvertUtil.convertToString(run).trim().isEmpty()) {
                        iscontinue = true;
                        j++;
                    }
                } else {
                    String tempText = convertedParagraph2.getText();
                    System.out.println(tempText.replaceAll(" ",""));
                    if("".equals(tempText.replaceAll(" ",""))){
                        iscontinue = true;
                        j++;
                    }
                }
            }
            if(iscontinue){
                continue;
            }
            System.out.println(i + "---" + j);
            if (elementName1.equals(elementName2)) {
                if ("PARAGRAPH".equals(elementName1)) {
                    // 段落对比
                    if (paragraphCompareHandlers == null || paragraphCompareHandlers.size() == 0) {
                        List<CjCompareJobResultEntity> tempCompareResultList = new DefaultParagraphCompareHandler()
                                .doCompare((XWPFParagraph) currentElement1, (XWPFParagraph) currentElement2, document1, compareItemsDto);
                        addPage(tempCompareResultList, page);
                        resultList.addAll(tempCompareResultList);
                    } else {
                        for (IParagraphCompareHandler paragraphCompareHandler : paragraphCompareHandlers) {
                            List<CjCompareJobResultEntity> tempCompareResultList = paragraphCompareHandler
                                    .doCompare((XWPFParagraph) currentElement1, (XWPFParagraph) currentElement2, document1, compareItemsDto);
                            addPage(tempCompareResultList, page);
                            resultList.addAll(tempCompareResultList);
                        }
                    }
                } else if ("TABLE".equals(elementName1)) {
                    // 表格对比
                    if (tableCompareHandlers == null || tableCompareHandlers.size() == 0) {
                        List<CjCompareJobResultEntity> tempCompareResultList = new DefaultTableCompareHandler()
                                .doCompare((XWPFTable) currentElement1, (XWPFTable) currentElement2, compareItemsDto);
                        addPage(tempCompareResultList, page);
                        resultList.addAll(tempCompareResultList);
                    } else {
                        for (ITableCompareHandler tableCompareHandler : tableCompareHandlers) {
                            List<CjCompareJobResultEntity> tempCompareResultList = tableCompareHandler
                                    .doCompare((XWPFTable) currentElement1, (XWPFTable) currentElement2, compareItemsDto);
                            addPage(tempCompareResultList, page);
                            resultList.addAll(tempCompareResultList);
                        }
                    }
                }
            } else {
                // 将元素补充一致，并记录缺失项
                CjCompareJobResultEntity resultEntity = compareElementDiff(document1, document2
                    , currentElement1, currentElement2
                    , elementName1, elementName2);
                resultEntity.setPageno(page);
                resultList.add(resultEntity);
            }
            i++;
            j++;
        }
        // 删除添加的段落
        delParagraphs(document1);
        return resultList;
    }

    public void delParagraphs(XWPFDocument document) {
        // 获取文档中的段落列表
        String section = SectionFlag;
        List<Integer> indexesToDelete = new ArrayList<>();
        int index = 0;
        for (IBodyElement bodyElement : document.getBodyElements()) {
            if (bodyElement instanceof XWPFParagraph) {
                XWPFParagraph convertedParagraph = (XWPFParagraph) bodyElement;
                // 对转换后的 XWPFParagraph 对象进行操作
                if(convertedParagraph.getRuns().size()>0){
                    XWPFRun run = convertedParagraph.getRuns().get(0);
                    if(section.equals(run.getText(0))){
                        indexesToDelete.add(index);
                    }
                }
            }
            index++;
        }
        for (int i = indexesToDelete.size() - 1; i >= 0; i--) {
            int deleteIndex = indexesToDelete.get(i);
            document.removeBodyElement(deleteIndex);
        }
    }

    public void addPage(List<CjCompareJobResultEntity> compareResultList, int page){
        for(CjCompareJobResultEntity resultEntity : compareResultList){
            resultEntity.setPageno(page);
        }
    }

    /**
     * description 获取目标段落所在的页码
     *
     * @param document
     * @param targetParagraph
     * @return int
     * @author hdy
     * @date 2023-07-24
     * @modify
     */
    private int getSectionIndex(XWPFDocument document, IBodyElement targetElement) {
        String section = SectionFlag;
        int sectionIndex = 1;
        for (IBodyElement bodyElement : document.getBodyElements()) {
            if (bodyElement instanceof XWPFParagraph) {
                XWPFParagraph convertedParagraph = (XWPFParagraph) bodyElement;
                // 对转换后的 XWPFParagraph 对象进行操作
               if(convertedParagraph.getRuns().size()>0){
                   XWPFRun run = convertedParagraph.getRuns().get(0);
                   if(section.equals(run.getText(0))){
                       sectionIndex++;
                   }
               }
            }
            if (bodyElement == targetElement) {
                // 如果相同，直接结束
                break;
            }
        }
        return sectionIndex;
    }
    /**
     * @param document1:
     * @param document2:
     * @param currentElement1:
     * @param currentElement2:
     * @param elementName1:
     * @param elementName2:
     * @description: 比较元素差异
     * @return: com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity
     * @author: zhanglongfei
     * @date: 2023/2/22 15:28
     * @modify:
     */
    private CjCompareJobResultEntity compareElementDiff(XWPFDocument document1,
        XWPFDocument document2
        , IBodyElement currentElement1, IBodyElement currentElement2
        , String elementName1, String elementName2) {
        CjCompareJobResultEntity resultEntity = createNewResultEntity();
        XWPFDocument document;
        XWPFTable table;
        XWPFParagraph paragraph;
        List<String> includes = new ArrayList<>();
        includes.add("");
        includes.add("TABLE");
        // 段落和表格的对应，则向表格所在的文档插入另一个文档的段落
        if (includes.indexOf(elementName1) > -1 && "PARAGRAPH".equals(elementName2)) {
            document = document1;
            table = (XWPFTable) currentElement1;
            paragraph = (XWPFParagraph) currentElement2;
            resultEntity.setDifftype(CjSystemConst.CjCompareJobResultDiffType.Add);
            resultEntity.setDoccontent2("存在该段落");
            resultEntity.setDoccontent1("缺少该段落");
            resultEntity.setPageno(PoiWordUtil.getTablePos(document, table));
            // 补充段落
            int paragraphNo = PoiWordUtil.insertCopyParagraph(document, table, paragraph);
            resultEntity.setParagraphno(paragraphNo);
        } else if ("PARAGRAPH".equals(elementName1) && includes.indexOf(elementName2) > -1) {
            document = document2;
            table = (XWPFTable) currentElement2;
            paragraph = (XWPFParagraph) currentElement1;
            resultEntity.setDifftype(CjSystemConst.CjCompareJobResultDiffType.Del);
            resultEntity.setDoccontent1("存在该段落");
            resultEntity.setDoccontent2("缺少该段落");
            resultEntity.setPageno(PoiWordUtil.getTablePos(document, table));
            // 补充段落
            int paragraphNo = PoiWordUtil.insertCopyParagraph(document, table, paragraph);
            resultEntity.setParagraphno(paragraphNo);
        } else if ("".equals(elementName1) && "TABLE".equals(elementName2)) {
            document = document1;
            table = (XWPFTable) currentElement2;
            resultEntity.setDifftype(CjSystemConst.CjCompareJobResultDiffType.Add);
            resultEntity.setDoccontent2("存在该表格");
            resultEntity.setDoccontent1("缺少该表格");
            // 补充表格
            int tableNo = PoiWordUtil.insertCopyTable(document, null, table);
            resultEntity.setPageno(tableNo);
            resultEntity.setTableno(tableNo);
        } else if ("TABLE".equals(elementName1) && "".equals(elementName2)) {
            document = document2;
            table = (XWPFTable) currentElement1;
            resultEntity.setDifftype(CjSystemConst.CjCompareJobResultDiffType.Del);
            resultEntity.setDoccontent1("存在该表格");
            resultEntity.setDoccontent2("缺少该表格");
            // 补充表格
            int tableNo = PoiWordUtil.insertCopyTable(document, null, table);
            resultEntity.setPageno(tableNo);
            resultEntity.setTableno(tableNo);
        } else {
            throw new ServiceException("不支持的元素类型");
        }
        return resultEntity;
    }

}
